#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import subprocess
import time
import urllib2
import json

class WeChat:
    def __init__(self):
        self.CORPID = 'wwe25fc490619d43f1'  # 企业ID，在管理后台获取
        self.CORPSECRET = 'tpYtHFMRRBDJ1clLcglTs-72LsOvgvI13yj70Pj2NqQ'  # 自建应用的Secret，每个自建应用里都有单独的secret
        self.AGENTID = '1000002'  # 应用ID，在后台应用中获取
        self.TOUSER = "@all"  # 接收者用户名,多个用户用|分割
        self.CURRENTTIME = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        self.getCurrentIP()

    def getCurrentIP(self):
        self.IP = self.runCommand("ip a |grep 'ens'|grep -w inet|awk '{print $2}'|awk -F '/' '{print $1}'").strip() or self.runCommand("ip a |grep 'bond0'|grep -w inet|awk '{print $2}'|awk -F '/' '{print $1}'").strip()

    def _get_access_token(self):

        url_access_token = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s" % (self.CORPID, self.CORPSECRET)
        req = urllib2.Request(url_access_token)
        response = urllib2.urlopen(req)
        data = json.loads(response.read())
        return data["access_token"]

    def get_access_token(self):
        """
        获取token
        :return: access_token
        """
        try:
            with open('./access_token.conf', 'r') as f:
                t, access_token = f.read().split()
        except:
            with open('./access_token.conf', 'w') as f:
                access_token = self._get_access_token()
                cur_time = time.time()
                f.write('\t'.join([str(cur_time), access_token]))
                return access_token
        else:
            cur_time = time.time()
            if 0 < cur_time - float(t) < 7260:
                return access_token
            else:
                with open('./access_token.conf', 'w') as f:
                    access_token = self._get_access_token()
                    f.write('\t'.join([str(cur_time), access_token]))
                    return access_token

    def send_data(self, message):
        """
        企业微信告警
        :param message: 告警内容
        :return: errmsg
        """
        send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + self.get_access_token()
        send_values = {
            "touser": self.TOUSER,
            "msgtype": "text",
            "agentid": self.AGENTID,
            "text": {
                "content": message
                },
            "safe": "0"
            }
        send_msges = json.dumps(send_values).encode('UTF-8')
        request = urllib2.Request(send_url, send_msges)
        conn = urllib2.urlopen(request).read()
        content_json = json.loads(conn)
        return content_json["errmsg"]

    def runCommand(self,cmd):
        """
        :param command: 所执行的命令
        :return: 命令执行的结果
        """
        ret = subprocess.Popen(cmd, shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        return ret.stdout.read().strip()

    def getMem(self):
        mem = {}
        with open('/proc/meminfo', 'r') as f:
            memCon = f.readlines()
        for line in memCon:
            names = line.split(':')[0]
            values = line.split(':')[1].split()[0]
            mem[names] = float(values)
        try:
            version = self.runCommand("cat /etc/redhat-release|grep -E '[0-9]\.'|awk -F '.' '{print $1}'|awk '{print $NF}'")
            if int(version) == 6:
                mem['Free'] = mem['MemFree'] + mem['Buffers'] + mem['Cached']
            elif int(version) == 7:
                mem['Free'] = mem['MemAvailable']
            else:
                print(version)
        except Exception as e:
            version = self.runCommand("cat /etc/redhat-release|grep -E '[0-9]\.'|awk -F '.' '{print $1}'|awk '{print $NF}'")
            if int(version) == 7:
                mem['MemUsed'] = mem['MemTotal'] - mem['MemAvailable']
            else:
                print(version, e)
        mem['FreeRate'] = (mem['Free'] / mem['MemTotal']) * 100
        return mem["FreeRate"]

    def getMemfreeRate(self):
        """
        应用程序可用内存/系统物理内存剩余>70%内存充足
        应用程序可用内存/系统物理内存剩余<20%内存不足，需要增加内存
        20%<应用程序可用内存/系统物理内存剩余<70%内存基本够用
        :return: None or 告警内容
        """
        freeRate = self.getMem()
        percentage = "%.2f%%" % freeRate
        if freeRate<=20:
            # 返回结构
            return "企业通讯录IP:"+self.IP+"\n告警项:内存不足,内存空闲率小于20%\n内存空闲率为:{percentage}\n告警时间:{currentTime}".format(percentage=percentage,currentTime=self.CURRENTTIME)
        print("内存空闲率:%s%%"%percentage)
        return None



    def getCpuLoadAverage(self):
        """
        获取cpu核心数:cat /proc/cpuinfo| grep 'model name'| wc -l
        获取当前负载情况:uptime
        :return: None or 告警内容
        """
        cpuCores = float(self.runCommand("cat /proc/cpuinfo| grep 'model name'| wc -l").strip())
        _,_,minute1,minute5,minute15 = self.runCommand("uptime|awk -F ',' '{print $(NF-2),$(NF-1),$NF}'").split()
        minute1, minute5, minute15 =  minute1.split(":")[-1].strip(),minute5.strip(),minute15.strip()
        minute1, minute5, minute15 = float(minute1), float(minute5), float(minute15)
        if minute15 >= cpuCores:
            # 返回结果
            return "企业通讯录IP:"+self.IP+'\n告警项:负载过高\ncup核心数:{cpuCores}\n当前负载为:{crtAverage}\n告警时间:{currentTime}'.format(cpuCores=cpuCores,crtAverage=minute15,currentTime=self.CURRENTTIME)
        print("CPU当前负载:%s"%minute5)
        return None

    def getCpuUsedRate(self):
        """
        统计cpu使用率
        :return: None
        """
        result = float(self.runCommand("mpstat|tail -n1|awk '{print $NF}'").strip())
        if result<=20:
            return "企业通讯录IP:"+self.IP+"\n告警项:cpu空闲不足20%\n当前cpu空闲:{result}%\n告警时间:{currentTime}".format(result=result,currentTime=self.CURRENTTIME)
        print("CPU当前空闲率:%d%%"%result)
        return None

    def getDiskUtilization(self):
        """
        获取磁盘空间使用率
        :return: None
        """
        resultDevs = self.runCommand("timeout 3 df -P | grep /dev | awk '{print $NF}'").split("\n")
        resultRate = self.runCommand("timeout 3 df -P | grep /dev | awk '{print $5}' | sed 's/%//g'").split("\n")
        result = []
        for dev,rate in zip(resultDevs,resultRate):
            if rate.strip():
                rate = int(rate.strip())
                if rate>90:
                    result.append("企业通讯录IP:"+self.IP+"\n告警项:磁盘空间不足\n盘符:{dev}\n空间使用率:{rate}%\n告警时间:{currentTime}".format(dev=dev,rate=rate,currentTime=self.CURRENTTIME))

                print("磁盘:%s\t空间使用率:%s%%" % (dev, rate))
        return "\n".join(result)

    def getDiskIo(self):
        """
        获取磁盘io空闲率，小于70%触发告警
        :return:
        """

        result = float(self.runCommand("iostat -x|head -n4|tail -n1|awk '{print $NF}'").strip())
        if result <=70:
            # 返回结果
            return "企业通讯录IP:"+self.IP+"\n告警项:磁盘io过高\n%util百分比:{util}%\n告警时间:{currentTime}".format(util=result,currentTime=self.CURRENTTIME)

        print("磁盘IO---%%util百分比:%s%%"%result)
        return None

    def sendStr(self):
        self.testType(1)
        self.testType(2)
        self.testType(3)
        self.testType(4)
        self.testType(5)

    def testType(self,num):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect(("10.1.19.33", 9100))  # 连接服务器
        if num == 1:
            # 获取内存
            memFreeRate = self.getMemfreeRate()
            if memFreeRate:
                sock.send(memFreeRate)
        if num == 2:
            #cpu负载
            cpuLoadAverage = self.getCpuLoadAverage()
            if cpuLoadAverage:
                sock.send(cpuLoadAverage)
        if num == 3:
            # cpu使用率
            cpuUsedRate = self.getCpuUsedRate()
            if cpuUsedRate:
                sock.send(cpuUsedRate)
        if num == 4:
            # 磁盘空间使用率
            diskUtilization = self.getDiskUtilization()
            if diskUtilization:
                sock.send(diskUtilization)
        if num == 5:
            # 磁盘io空闲率
            diskIo = self.getDiskIo()
            if diskIo:
                sock.send(diskIo)

        sock.close()  # 关闭套接字...

if __name__ == '__main__':
    wx = WeChat()
    wx.sendStr()

